package com.zhanghaijun.createCode.util;

import com.enniu.commons.basic.Answer;
import com.zhanghaijun.createCode.bean.AdSynchronousBean;
import com.zhanghaijun.createCode.bean.AdUser;
import com.zhanghaijun.createCode.bean.OuBean;
import com.zhanghaijun.createCode.security.AdService;

import java.util.Arrays;
import java.util.Hashtable;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InitialDirContext;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;

/**
 * Created by zhanghaijun on 15/5/19.
 */
public class AdUtil {

    private static String dcBase2="dc=51,dc=nb";
    /**
     * 51.nb
     * ad�ĵ�ַ��10.0.80.10,
     10.0.80.11
     monitor
     563kpjv0479d
     */

    private static String dcBase="ou=U51,dc=51,dc=nb";

    private static DirContext ds;

    static{
       //String keystore = "/Library/Java/JavaVirtualMachines/jdk1.7.0_75.jdk/Contents/Home/jre/lib/security/cacerts";

       // String keystore = "/Users/zhanghaijun/Library/Caches/IntelliJIdea14/tasks/cacerts";
        //System.setProperty("javax.net.ssl.trustStore", keystore);
        //System.setProperty("javax.net.ssl.trustStorePassword","changeit");
        //System.setProperty("javax.net.debug", "ssl,handshake");


        Hashtable ldapEnv = new Hashtable();
        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
        ldapEnv.put(Context.PROVIDER_URL, "ldap://10.0.80.10:389");
        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
        ldapEnv.put(Context.SECURITY_PRINCIPAL, "monitor@51.nb");
        ldapEnv.put(Context.SECURITY_CREDENTIALS, "563kpjv0479d"); // ����

        //ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
        try{
            ds = new InitialLdapContext(ldapEnv, null);
        }catch (Exception e){
            e.printStackTrace();
        }
//        Hashtable ldapEnv = new Hashtable();
//        ldapEnv.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
//        ldapEnv.put(Context.PROVIDER_URL, "LDAP://10.0.40.104:389");
//        ldapEnv.put(Context.SECURITY_AUTHENTICATION, "simple");
//        ldapEnv.put(Context.SECURITY_PRINCIPAL, "administrator@testad.nb51");
//        ldapEnv.put(Context.SECURITY_CREDENTIALS, "51test.com"); // 密码
//        ldapEnv.put(Context.SECURITY_PROTOCOL, "ssl");
//        try{
//            ds = new InitialLdapContext(ldapEnv, null);
//        }catch (Exception e){
//            e.printStackTrace();
//        }
//        String keystore = "/Library/Java/JavaVirtualMachines/jdk1.7.0_75.jdk/Contents/Home/jre/lib/security/cacerts";
//        System.setProperty("javax.net.ssl.trustStore", keystore);
//
//        Properties env = new Properties();
//        String adminName = "administrator@testad.nb51";// username@domain
//        String adminPassword = "51test.com";// password
//        String ldapURL = "LDAP://10.0.40.104:636";// ip:port
//        env.put(Context.INITIAL_CONTEXT_FACTORY,
//                "com.sun.jndi.ldap.LdapCtxFactory");
//        env.put(Context.SECURITY_AUTHENTICATION, "simple");// "none","simple","strong"
//        env.put(Context.SECURITY_PRINCIPAL, adminName);
//        env.put(Context.SECURITY_CREDENTIALS, adminPassword);
//        env.put(Context.PROVIDER_URL, ldapURL);
//        env.put(Context.SECURITY_PROTOCOL, "ssl");
//        if (ds == null) {
//            try{
//                ds = new InitialDirContext(env);
//            }catch (Exception e){
//                e.printStackTrace();
//            }
//        }
    }


    /**
     * 添加组织
     */
    public static void addOu(OuBean ouBean) throws NamingException {
        Attributes attrs = new BasicAttributes();
        attrs.put("displayName", ouBean.getDescription());
        Attribute objclass = new BasicAttribute("objectClass");
        objclass.add("organizationalUnit");
        objclass.add("top");

        attrs.put(objclass);
        attrs.put("objectCategory",ouBean.getObjectCategory());
        attrs.put("ou",ouBean.getOu());

        attrs.put("description", ouBean.getDescription());// monitor对应组织机构�?        //ds.createSubcontext(ouBean.getSubContext(), attrs);

        PrintUtil.println(ouBean.getSubContext());
        ds.createSubcontext(ouBean.getSubContext(), attrs);
    }


    /**
     * 添加组织
     */
    public static void addOu(String ou) throws NamingException {
        System.out.println("Adding ou...");
        Attributes attrs = new BasicAttributes();
        attrs.put("displayName", "新建组织");
        attrs.put("pwdLastSet","-1");

        // the following attribute has two values
        Attribute objclass = new BasicAttribute("objectClass");
        objclass.add("organizationalUnit");
        objclass.add("top");

        attrs.put(objclass);
        attrs.put("objectCategory","CN=Organizational-Unit,CN=Schema,CN=Configuration,DC=testad,DC=nb51");
        attrs.put("ou",ou);
        attrs.put("description","Here ou's DepCode");// monitor对应组织机构�?

        ds.createSubcontext("ou=" + ou + "," + dcBase, attrs);
        System.out.println("Add  Ou complete.");
    }

    /**
     * 添加人员
     */
    public static void add(AdUser adUser) throws Exception {
        System.out.println("Adding...");
        Attributes attrs = new BasicAttributes();
        attrs.put("displayName",adUser.getDisplayName());
        attrs.put("uid",adUser.getUid());
       //mail
        attrs.put("sn",adUser.getSn());
        attrs.put("cn",adUser.getCn());
        if(adUser.getStreetAddress()!=null){
             attrs.put("streetAddress",adUser.getStreetAddress());
        }
//        attrs.put("msTsAllowLogon", true);
        attrs.put("sAMAccountName", adUser.getsAMAccountName());
        attrs.put("employeeId", adUser.getEmployeeId());
        attrs.put("userPassword", "12345@abc".getBytes());
//        String password="p123456qwe_@";
//        String newQuotedPassword = "/" + password + "/";
//        byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
//
//        attrs.put("unicodePwd", newUnicodePassword);


        attrs.put("userPrincipalName",adUser.getUserPrincipalName()+"@51.nb");
        attrs.put("userAccountControl", "544");//544启用�?        attrs.put("pwdLastSet", "-1");//
        attrs.put("pwdLastSet", "-1");
        // the following attribute has two values

        Attribute objclass = new BasicAttribute("objectClass");
        String[] attrObjectClassPerson = { "inetOrgPerson", "organizationalPerson", "person", "top","user"};
        Arrays.sort(attrObjectClassPerson);
        for (String ocp : attrObjectClassPerson) {
            objclass.add(ocp);
        }
        attrs.put(objclass);
        ds.createSubcontext(adUser.getSubContext(), attrs);
        System.out.println("Add complete.");

    }



    /**
     * 通过唯一名称
     */
    public static boolean getByDistinguishedName(String distinguishedName)throws Exception{

        SearchControls searchCtls = new SearchControls();
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        String searchFilter = "(&(distinguishedName="+ distinguishedName + "))";
        String searchBase = dcBase;

        String returnedAtts[] = {"displayName","name"};
        searchCtls.setReturningAttributes(returnedAtts);
        NamingEnumeration<SearchResult> entries = ds.search(searchBase,
                searchFilter, searchCtls);

        if(entries.hasMoreElements()){
            return true;
        }else{
            return false;
        }
    }

    /**
     * 通过唯一名称
     */
    public static boolean getByDistinguishedName2(String distinguishedName)throws Exception{

        SearchControls searchCtls = new SearchControls();
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        String searchFilter = "(&(distinguishedName="+ distinguishedName + "))";
        String searchBase = dcBase2;

        String returnedAtts[] = {"displayName","name"};
        searchCtls.setReturningAttributes(returnedAtts);
        NamingEnumeration<SearchResult> entries = ds.search(searchBase,
                searchFilter, searchCtls);

        if(entries.hasMoreElements()){
            return true;
        }else{
            return false;
        }
    }

    public static String createOUDistinguishedName(String[] ouNames){
        StringBuffer sb = new StringBuffer();
        for(String ouName:ouNames){
            sb.append("ou=").append(ouName).append(",");
        }
        sb.append(dcBase);
        return sb.toString();
    }

    public static String createOUDistinguishedName2(String[] ouNames){
        StringBuffer sb = new StringBuffer();
        for(String ouName:ouNames){
            sb.append("ou=").append(ouName).append(",");
        }
        sb.append(dcBase2);
        return sb.toString();
    }

    public static String createCnDistinguishedName(String[] ouNames,String personCN){
        StringBuffer sb = new StringBuffer();
        if(personCN!=null){
            sb.append("cn=").append(personCN).append(",");
        }
        for(String ouName:ouNames){
            sb.append("ou=").append(ouName).append(",");
        }
        sb.append(dcBase);
        return sb.toString();
    }


    /**
     *  同步成功 true
     *  同步失败 false
     * @param adSynchronousBean
     * @return
     */
    public static boolean adSynchronous(AdSynchronousBean adSynchronousBean)throws Exception{
        String rootOu = createOUDistinguishedName2(new String[]{"U51"});
        boolean rootIsExist = getByDistinguishedName2(rootOu);
        if(!rootIsExist){
            OuBean ouBean= new OuBean();
            ouBean.setDescription("U51");
            ouBean.setDisplayName("U51");
            ouBean.setOu("U51");
            ouBean.setSubContext(rootOu);
            addOu(ouBean);
        }




        String company = adSynchronousBean.getCompany();
        String bussinessDept = adSynchronousBean.getBussinessDept();
        String orgStr =adSynchronousBean.getOrg();
        //组织架构
        if(company!=null&&bussinessDept==null&&orgStr==null){
            String ouDistinguishedName = createOUDistinguishedName(new String[]{company});
            boolean res = getByDistinguishedName(ouDistinguishedName);
            if(!res){
                OuBean ouBean= new OuBean();
                ouBean.setDescription(company);
                ouBean.setDisplayName(company);
                ouBean.setOu(company);
                ouBean.setSubContext(ouDistinguishedName);
                addOu(ouBean);
            }
            AdUser adUser = adSynchronousBean.getAdUser();

            String cnDistinguishedName = createCnDistinguishedName(new String[]{company}, adUser.getCn());
            boolean res2 = getByDistinguishedName(cnDistinguishedName);
            if (!res) {
                adUser.setSubContext(cnDistinguishedName);
                add(adUser);
                //update(cnDistinguishedName);
            }
            try{
                AdService.changePassword(adUser.getsAMAccountName(), "", "12345@abc");



            }catch (Exception e) {
                e.printStackTrace();
                PrintUtil.println("error id is=====" + adUser.getsAMAccountName());
            }


        }else if(company!=null&&bussinessDept!=null&&orgStr==null){
            String ouDistinguishedName = createOUDistinguishedName(new String[]{company});
            boolean res = getByDistinguishedName(ouDistinguishedName);
            if(!res){
                OuBean ouBean= new OuBean();
                ouBean.setOu(company);
                ouBean.setDescription(company);
                ouBean.setDisplayName(company);
                ouBean.setSubContext(ouDistinguishedName);
                addOu(ouBean);
            }

            String ouDistinguishedName2 = createOUDistinguishedName(new String[]{bussinessDept,company});
            boolean res2 = getByDistinguishedName(ouDistinguishedName2);
            if(!res2){
                OuBean ouBean= new OuBean();
                ouBean.setOu(bussinessDept);
                ouBean.setDescription(bussinessDept);
                ouBean.setDisplayName(bussinessDept);
                ouBean.setSubContext(ouDistinguishedName2);
                addOu(ouBean);
            }
            AdUser adUser = adSynchronousBean.getAdUser();

            String cnDistinguishedName = createCnDistinguishedName(new String[]{bussinessDept,company}, adUser.getCn());
            boolean cnRes2 = getByDistinguishedName(cnDistinguishedName);
            if (!cnRes2) {
                adUser.setSubContext(cnDistinguishedName);
                add(adUser);
                //update(cnDistinguishedName);
            }

            try{
                AdService.changePassword(adUser.getsAMAccountName(),"","12345@abc");
            }catch (Exception e) {
                e.printStackTrace();
                PrintUtil.println("error id is=====" + adUser.getsAMAccountName());
            }
        }else if(company!=null&&bussinessDept!=null&&orgStr!=null){
            String ouDistinguishedName = createOUDistinguishedName(new String[]{company});
            boolean res = getByDistinguishedName(ouDistinguishedName);
            if(!res){
                OuBean ouBean= new OuBean();
                ouBean.setOu(company);
                ouBean.setDescription(company);
                ouBean.setDisplayName(company);
                ouBean.setSubContext(ouDistinguishedName);
                addOu(ouBean);
            }

            String ouDistinguishedName2 = createOUDistinguishedName(new String[]{bussinessDept,company});
            boolean res2 = getByDistinguishedName(ouDistinguishedName2);
            if(!res2){
                OuBean ouBean= new OuBean();
                ouBean.setDescription(bussinessDept);
                ouBean.setDisplayName(bussinessDept);
                ouBean.setOu(bussinessDept);
                ouBean.setSubContext(ouDistinguishedName2);
                addOu(ouBean);
            }

            String ouDistinguishedName3 = createOUDistinguishedName(new String[]{orgStr,bussinessDept,company});
            boolean res3 = getByDistinguishedName(ouDistinguishedName3);
            if(!res3){
                OuBean ouBean= new OuBean();
                ouBean.setDescription(orgStr);
                ouBean.setDisplayName(orgStr);
                ouBean.setOu(orgStr);
                ouBean.setSubContext(ouDistinguishedName3);
                addOu(ouBean);
            }

            AdUser adUser = adSynchronousBean.getAdUser();
            String cnDistinguishedName = createCnDistinguishedName(new String[]{orgStr,bussinessDept,company}, adUser.getCn());
            boolean cnRes2 = getByDistinguishedName(cnDistinguishedName);
            PrintUtil.println(cnRes2+"====================");
            if (!cnRes2) {
                adUser.setSubContext(cnDistinguishedName);
                add(adUser);
               // update(cnDistinguishedName);
            }

            try{
                AdService.changePassword(adUser.getsAMAccountName(),"","12345@abc");

            }catch (Exception e) {
                e.printStackTrace();
                PrintUtil.println("error id is=====" + adUser.getsAMAccountName());
            }
        }else{
            return false;
        }
        return true;
    }


    public static void search(String queryString) throws NamingException {
        System.out.println("Searching...");
        SearchControls searchCtls = new SearchControls();


        // Specify the search scope
        searchCtls.setSearchScope(SearchControls.SUBTREE_SCOPE);
        // specify the LDAP search filter
//        String searchFilter = "uid=test";
        //String searchFilter = "(&(objectCategory=person)(objectClass=user)(name="+ queryString + "))";
        //ɸѡ����Ϊ�û�����֯

        String searchFilter = "(&(objectClass=user)(userPrincipalName="+ queryString + "))";

        // Specify the Base for the search
        String searchBase = dcBase2;

        // Specify the attributes to return
        String returnedAtts[] = { "displayName"};
        searchCtls.setReturningAttributes(returnedAtts);

        // Search for objects using the filter
        NamingEnumeration<SearchResult> entries = ds.search(searchBase,
                searchFilter, searchCtls);

        // Loop through the search results
        while (entries.hasMoreElements()) {
            SearchResult entry = entries.next();
            System.out.println(">>>" + entry.getName());
            // Print out the groups
            Attributes attrs = entry.getAttributes();
            if (attrs != null) {
                for (NamingEnumeration<? extends Attribute> names = attrs
                        .getAll(); names.hasMore();) {
                    Attribute attr = names.next();
                    System.out.println("AttributeID: " + attr.getID());
                    for (NamingEnumeration<?> e = attr.getAll(); e.hasMore();) {
                        System.out.println("Attributes:" + e.next());
                    }
                }
            }
        }
        System.out.println("Search complete.");
    }



    public static void update(String cnDistinguishedName) throws Exception {
        PrintUtil.println("==========update:"+cnDistinguishedName);
        ModificationItem[] mods = new ModificationItem[1];
        String password="p123456qwe_@";
        String newQuotedPassword = "/" + password + "/";
        byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
        mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
                new BasicAttribute("unicodePwd", newUnicodePassword));
        //ModificationItem[] mods = new ModificationItem[1];
        //Attribute attr = new BasicAttribute("userPassword","123456qwe"); //重置密码

        // Support add, replace and remove an attribute.
        //mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE, attr);
        ds.modifyAttributes(cnDistinguishedName,mods);
    }




    public static void add(String cn,String ou) throws Exception {

        Attributes attrs = new BasicAttributes();
        attrs.put("displayName", "����");
        attrs.put("uid", cn);
        attrs.put("sn", cn);
        attrs.put("cn", cn);
        attrs.put("streetAddress", "12312312");
//        attrs.put("msTsAllowLogon", true);
        attrs.put("sAMAccountName", cn);
        attrs.put("employeeId", cn);
        attrs.put("userPassword", "111111".getBytes());
        attrs.put("userPrincipalName", cn+"@testad.nb51");
        attrs.put("userAccountControl","544");//544启用�?        attrs.put("pwdLastSet","-1");//
        attrs.put("pwdLastSet", "-1");//


//        String password="p123456qwe_@";
//        String newQuotedPassword = "/" + password + "/";
//        byte[] newUnicodePassword = newQuotedPassword.getBytes("UTF-16LE");
//
//        attrs.put("unicodePwd", newUnicodePassword);
        // the following attribute has two values

        Attribute objclass = new BasicAttribute("objectClass");
        String[] attrObjectClassPerson = { "inetOrgPerson", "organizationalPerson", "person", "top","user"};
        Arrays.sort(attrObjectClassPerson);
        for (String ocp : attrObjectClassPerson) {
            objclass.add(ocp);
        }

//        objclass.add("inetOrgPerson");  //inetOrgPerson 类型衍生自user
//        objclass.add("user");
//        objclass.add("ou");
        attrs.put(objclass);

        ds.createSubcontext("cn="+cn+",ou="+ou+","+dcBase, attrs);
    }

    public static void main(String[] args)throws Exception{
        //add("zhangsan22","��ţ");
        search("zhanghaijun@51.nb");
    }

    public static void addFirstOu(String ou)throws Exception{
        boolean res = getByDistinguishedName(createOUDistinguishedName(new String[]{"ou"}));
        PrintUtil.println("add now");
        if(!res){
            OuBean ouBean = new OuBean();
            ouBean.setDescription(ou);
            ouBean.setDisplayName(ou);
            ouBean.setOu(ou);
            addOu(ouBean);
        }
    }




    public static void close()throws Exception{

        ds.close();
    }













}
